#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdlib.h>
#include <iostream>
#include <vector>

typedef void (*callback_t)();

enum
{
    OK,
    USAGE_ERR
};

void Task()
{
    int cnt = 5;
    while(cnt--)
    {
        printf("我是一个子进程, 我在完成Task任务, pid: %d, ppid:%d, cnt: %d\n", getpid(), getppid(), cnt);
        sleep(1);
    }
}

void Hello()
{
    int cnt = 5;
    while(cnt--)
    {
        printf("我是一个子进程, 我在完成Hello任务, pid: %d, ppid:%d, cnt: %d\n", getpid(), getppid(), cnt);
        sleep(1);
    }
}
///////////////////////////////
// 一般而言：
// 输入: const &
// 输出：*
// 输入输出: &
void CreateChildProcess(int num, std::vector<pid_t> *subs, callback_t cb)//subs为输出型参数
{
    for(int i = 0; i < num; i++)
    {
        pid_t id = fork();
        if(id == 0)
        {
            //child
            cb();
            exit(0);
        }
        // 父进程
        subs->push_back(id);
    }
}

void WaitAllChild(const std::vector<pid_t> &subs)
{
    for(const auto &pid : subs)
    {
        int status = 0;
        pid_t rid = waitpid(pid, &status, 0);
        if(rid > 0)
        {
            printf("子进程: %d Exit, exit code: %d\n", rid, WEXITSTATUS(status));
        }
    }
}

// 启停多进程的方案
// ./myproc 5 --- 我要创建五个子进程
int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        std::cout << "Usage: " << argv[0] << " process_num" << std::endl;
        exit(USAGE_ERR);
    }
    int num = std::stoi(argv[1]);
    std::vector<pid_t> subs;
    //std::vector<callback_t> cbs;
    // 创建多进程
    CreateChildProcess(num, &subs, Hello);
    // 父进程
    WaitAllChild(subs);

    return OK;
}


//int main()
//{
//  printf("我是一个进程： pid: %d, ppid: %d\n", getpid(), getppid());
//
//  pid_t id = fork();
//  if(id < 0)
//  {
//    perror("fork");
//    exit(1);
//  }
//  else if(id == 0)
//  {
//    //子进程
//    int cnt = 5;
//    while(cnt--)
//    {
//       printf("我是一个子进程： pid: %d, ppid: %d\n", getpid(), getppid());
//       sleep(1);
//    }
//    exit(10);
//  }
//  else
//  {
//     //父进程
//     while(1)
//     {
//        int status = 0;
//        pid_t rid = waitpid(id, &status, WNOHANG);
//        if(rid > 0)
//        {
//           printf("wait success, 退出的子进程是：%d, exit_code: %d\n", rid, WEXITSTATUS(status));
//           break;
//        }
//        else if(rid == 0)
//        {
//          printf("子进程正在运行，父进程还需要等待！\n");
//          usleep(100000);
//        }
//        else
//        {
//           perror("waitpid");
//           break;
//        }
//      }
//  //  int status = 0;
//  //  //父进程阻塞等待
//  //  pid_t rid = waitpid(id, &status, 0);
//  //  if(rid > 0)
//  //  {
//  //    if(WIFEXITED(status))
//  //    {
//  //         printf("wait success, 退出的子进程是：%d, exit_code: %d\n", rid ,WEXITSTATUS(status)) ;
//  //    }
//  //    else
//  //    {
//  //        printf("进程异常退出\n");
//  //    }
//  //  }
//  //  else
//  //  {
//  //      printf("ret: %d\n", rid);
//  //      perror("waitpid");//waitpid执行失败返回-1，同时设置errno
//  //  }
//  //}
//}
//}
